package cn.haocxy.jfm.gui;

import javafx.scene.Node;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import cn.haocxy.jfm.file.FileIcons;
import cn.haocxy.jfm.filelist.FileItem;

/**
 * 图标区域
 * <p>
 * 由图标和图标背景组成
 * 
 * @author 蔡心宇
 *
 */
class IconArea {

	private final FileItemGUI itemGUI;

	private final StackPane iconArea = new StackPane();

	private final Icon icon;

	private final IconBackground iconBack = new IconBackground();

	public IconArea(FileItemGUI itemGUI) {
		this.itemGUI = itemGUI;
		icon = new Icon(FileIcons.getIcon(itemGUI.getModel().getFileType()));

		iconArea.getChildren().add(iconBack.toNode());
		iconArea.getChildren().add(icon.toNode());

		setHandler();
	}

	public FileItem getFileItem() {
		return itemGUI.getModel();
	}

	public FileItemGUI getFileItemGUI() {
		return itemGUI;
	}
	
	/**
	 * 根据当前项是否被选择更新自己的外观
	 * 
	 * @param isSelected
	 *            当前文件项是否被选择
	 */
	public void update(boolean isSelected) {
		if (isSelected) {
			selected();
		} else {
			notSelected();
		}
	}

	public Node toNode() {
		return iconArea;
	}

	private void selected() {
		icon.normal();
		iconBack.update(iconArea.isHover());
	}

	private void notSelected() {
		iconBack.hide();
		icon.update(iconArea.isHover());
	}

	private void setHandler() {

		iconArea.addEventHandler(MouseEvent.MOUSE_ENTERED, e -> {
			if (FileItemMenuSingle.isShown()) {
				return;
			}
			update(itemGUI.getModel().isSelected());
		});

		iconArea.addEventHandler(MouseEvent.MOUSE_EXITED, e -> {
			if (FileItemMenu.isShown()) {
				return;
			}
			update(itemGUI.getModel().isSelected());
		});

		iconArea.addEventHandler(MouseEvent.MOUSE_RELEASED,
				this::handleMouseEvent);
	}

	private void handleMouseEvent(MouseEvent e) {
		
		e.consume();
		
		FileListPaneMenu.get().hide();
		
		// 如果菜单已打开且按下的不是右键, 则关闭菜单, 然后不进行任何操作直接返回
		if (FileItemMenu.isShown() && !e.getButton().equals(MouseButton.SECONDARY)) {
			FileItemMenu.hideMenu();
			return;
		}

		// 鼠标右键按下时在当前位置打开菜单
		if (e.getButton().equals(MouseButton.SECONDARY)) {

			FileItemMenu.showMenu(this, iconArea, e.getScreenX(),
					e.getScreenY());

		} else {

			if (e.getButton().equals(MouseButton.PRIMARY)) {

				// 点击主按键（通常为左键），根据按下次数处理。

				/*
				 * 为什么要 clickCount % 2 ?
				 * 
				 * clickCount表示当前键被连续按下的次数，连续按下表示以一个比较小的
				 * 间隔(实际上非常短只有0.5秒左右)按下多次，而且在这段时间内如果按下了其他键， 即使间隔很短，次数也会被归为1。
				 * 所以clickCount%2==1表示单击，clickCount% 2==0表示按下偶数次，即为双击。
				 * 
				 * 这样做，就解决了在切换路径后无法立刻响应单击和双击的问题，因为对于用户来说是双击， 而对于系统来说则是三击四击。
				 */

				int clickCount = e.getClickCount() % 2;
				if (clickCount == 1) {
					onSingleClick();
				} else { // if clickCount == 0
					reSingleClick(); // 因为双击事件总是跟随在单击事件后,所以要先去除单击事件造成的状态变化
					onDoubleClick();
				}

			}
		}
	}

	private void onSingleClick() {

		if (itemGUI.getModel().toFilePath().getParent().isWin32Root()) {
			return;
		}
		
		itemGUI.getModel().toggleSelected();
		update(itemGUI.getModel().isSelected());
	}

	// 发生双击事件时调用 , 去除之前的单击事件造成的影响
	private void reSingleClick() {

		if (itemGUI.getModel().toFilePath().getParent().isWin32Root()) {
			return;
		}
		
		itemGUI.getModel().toggleSelected();
		update(itemGUI.getModel().isSelected());
	}
	
	private void onDoubleClick() {

		if (itemGUI.getModel().toFilePath().isDirectory()) {

			if (itemGUI.getModel().toFilePath().canOpen()) {
				itemGUI.getModel().getFileListModel().setDir(itemGUI.getModel().toFilePath());
			} else {
				itemGUI.getFileListPane().info("权限不足  , 无法打开");
			}
			
		} else {

			try {
				itemGUI.getModel().open();
			} catch (Exception ex) {
				itemGUI.getFileListPane().info(ex.getMessage());
			}
		}

	}

	/**
	 * 右键菜单隐藏时调用这个方法告诉图标部分，使得图标部分可以改变自己的外观
	 */
	void _menuHidden() {
		update(itemGUI.getModel().isSelected());
	}

	/**
	 * 右键菜单打开后调用这个方法告诉图标部分，使得图标部分可以改变自己的外观
	 */
	void _menuShown() {
		update(itemGUI.getModel().isSelected());
	}
}
